
package com.yuanmei.datas;

import android.util.Log;

import com.yuanmei.common.Utils;
import com.yuanmei.model.TickQuote;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;

import javolution.io.Struct;
import io.realm.Realm;
import io.realm.RealmConfiguration;

@SuppressWarnings("deprecation")
public class PyTdxHistory {
    private static final String TAG = PyTdxHistory.class.getName();
    private final static short MAX_GET_COUNT = 2000;
    private final static boolean DEBUG = false;

    public static class TdxHistoryTransactionParams extends Struct {
        private final Unsigned32 date = new Unsigned32();
        private final Unsigned16 market = new Unsigned16();
        private final UTF8String code = new UTF8String(6);
        private final Unsigned16 start = new Unsigned16();
        private final Unsigned16 count = new Unsigned16();

        @Override
        public boolean isPacked() {
            return true; // 一定要加上这个，不然会出现对齐的问题
        }

        @Override
        public ByteOrder byteOrder() {
            return ByteOrder.LITTLE_ENDIAN; // 设置为小端数据
        }
    }


    private static short[] getHistoryRangeByDate(Socket client,
                                                 TdxHistoryTransactionParams origParam,
                                                 short off, short len,
                                                 List<TickQuote> ticksOfDay,
                                                 short preHeadMinutes, short preHeadSeconds) throws IOException {
        OutputStream out = client.getOutputStream();
        InputStream in = client.getInputStream();
        ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
        byteArrayStream.write(Utils.hexStringToByteArray("0c 01 30 01 00 01 12 00 12 00 b5 0f"));
        origParam.start.set(off);
        origParam.count.set(len);
        origParam.write(byteArrayStream);
        out.write(byteArrayStream.toByteArray());
        out.flush();

        if (DEBUG) {
            System.out.println("Send [" + off + " - " + (off + len) + "] cmd package:"
                    + Utils.byteArrayToHexString(byteArrayStream.toByteArray()));
        }

        byte[] body = PyTdxBase.getResponse(in);
        if (body == null) {
            throw new IOException("Error Get a empty history transcations response body");
        }

        int pos = 0;
        ByteBuffer bodyBuffer = ByteBuffer.wrap(body);
        byte[] shortBytes = new byte[2];
        bodyBuffer.get(shortBytes);
        pos += 2;
        short tickNum = ByteBuffer.wrap(shortBytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
        if (DEBUG) System.out.println("tickNum=" + tickNum);

        // skip 4 bytes
        pos += 4;

        short currMinutes = 0;
        short seconds = 0;
        short sina_step_second = 3;
        short saveHeadMinutes = 0;
        short saveHeadSeconds = 0;
        int last_price = 0;
        for (int i = 0; i < tickNum; i++) {
            // get tick time
            bodyBuffer.position(pos);
            bodyBuffer.get(shortBytes);
            short tMinutes = ByteBuffer.wrap(shortBytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
            if (currMinutes == 0) {
                currMinutes = tMinutes;
                if (0 != preHeadMinutes && preHeadMinutes == currMinutes) {
                    seconds = (short) (preHeadSeconds + sina_step_second);
                } else {
                    seconds = 0;
                }
                saveHeadMinutes = tMinutes;
            } else if (tMinutes != currMinutes) {
                if (saveHeadMinutes == currMinutes) {
                    saveHeadSeconds = seconds;
                }
                currMinutes = tMinutes;
                if (0 != preHeadMinutes && preHeadMinutes == currMinutes) {
                    seconds = (short) (preHeadSeconds + sina_step_second);
                } else {
                    seconds = 0;
                }
            } else {
                seconds += sina_step_second;
            }

            int tick = (tMinutes / 60) * 100 * 100 + (tMinutes % 60) * 100 + seconds;
            pos += 2;

            int[] results = PyTdxBase.get_price(bodyBuffer, pos);
            int price_raw = results[0];
            pos = results[1];

            results = PyTdxBase.get_price(bodyBuffer, pos);
            int vol = results[0];
            pos = results[1];

            results = PyTdxBase.get_price(bodyBuffer, pos);
            int buyorsell = results[0];
            pos = results[1];

            results = PyTdxBase.get_price(bodyBuffer, pos);
            pos = results[1];

            last_price = last_price + price_raw;
            TickQuote tQuote = new TickQuote(tick, vol, last_price,
                    ((buyorsell == 0) ? "买盘" : ((buyorsell == 1) ? "卖盘" : "中性")));
            if (i < 20 || i > (tickNum - 20)) {
                if (DEBUG)
                    System.out.println("No_" + i + " : " + tQuote.toString());
            }
            ticksOfDay.add(tQuote);
        }

        short[] result = new short[3];
        result[0] = saveHeadMinutes;
        result[1] = saveHeadSeconds;
        result[2] = tickNum;
        return result;
    }


    private static List<TickQuote> getHistoryTransactionData(
            short market,
            String code,
            int transactionDate) {

        TdxHistoryTransactionParams dateParam = new TdxHistoryTransactionParams();
        dateParam.date.set(transactionDate);
        dateParam.market.set(market);
        dateParam.code.set(code);

        String errorString;
        try {
            SocketAddress remoteAddress = new InetSocketAddress(PyTdxBase.getServerHost(), PyTdxBase.getServerPort());
            Socket client = new Socket();
            client.connect(remoteAddress, 5000);
            PyTdxBase.run_setup(client);

            Log.d(TAG,"PyTDX Success connect:" + PyTdxBase.getServerHost() + ":" + PyTdxBase.getServerPort());
            List<TickQuote> ticksOfDay = new ArrayList<>();
            short preHeadMinutes = 0;
            short preHeadSeconds = 0;
            short start = 0;
            short getTickCount;
            do {
                short[] ret = getHistoryRangeByDate(client, dateParam, start, MAX_GET_COUNT,
                        ticksOfDay, preHeadMinutes, preHeadSeconds);
                preHeadMinutes = ret[0];
                preHeadSeconds = ret[1];
                getTickCount = ret[2];
                Log.d(TAG, "preHeadMinutes=" + preHeadMinutes + ", preHeadSeconds=" +
                        preHeadSeconds + ", getTickCount = " + getTickCount);

                start += getTickCount;
            } while (getTickCount >= MAX_GET_COUNT);
            client.close();
            return ticksOfDay;
        } catch (NullPointerException e) {
            errorString = "fail jkp PyTDX history tick for get NullPointerException:" + e;
            System.out.println(errorString);
        } catch (IOException e) {
            errorString = "fail jkp PyTDX history tick for get IOException:" + e;
            System.out.println(errorString);
        }
        return null;
    }

    public static String downloadHistoryTickData(String netEaseCode, Date tickDate) {
        String errorString = "ok";
        short market = 0; // SZ
        if (netEaseCode.startsWith("0")) {
            market = 1; // SH
        }
        String code = netEaseCode.substring(1);
        List<TickQuote> dayQuotes = getHistoryTransactionData(market, code, Utils.getIDateFromDate(tickDate));
        if (null == dayQuotes) {
            errorString = "fail: PyTDX get history transaction data:" + netEaseCode + ":" + tickDate;
            Log.w(TAG, errorString);
            return errorString;
        }

        RealmConfiguration tickRealmConfig = new RealmConfiguration.Builder()
                .name(Utils.getTickRealmFile(netEaseCode, tickDate))
                .deleteRealmIfMigrationNeeded()
                .build();
        Realm realm = Realm.getInstance(tickRealmConfig);
//        先清理数据
        realm.beginTransaction();
        realm.deleteAll();
        realm.commitTransaction();

        realm.beginTransaction();
        for (TickQuote quote : dayQuotes) {
            realm.insertOrUpdate(quote);
        }
        realm.commitTransaction();

        realm.close();
        if (!Realm.compactRealm(tickRealmConfig)) {
            Log.w(TAG, "After PyTDX download tick data, compact realm fail");
        }
        return errorString;
    }


}
